#!/usr/bin/env python
# -*- coding: utf-8 -*-

from time import gmtime, strftime
import os

from shared.helper import render_to_response

from django.http import HttpResponse, Http404, HttpResponseRedirect
from django.shortcuts import get_object_or_404, redirect
from django.contrib.auth import authenticate, login
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required, permission_required
from django.core.mail import EmailMessage
from django.core.urlresolvers import reverse


from usermanagement.models import UserProfile
from usermanagement.forms import LoginForm, RegisterForm, ChangePasswordForm, LostPasswordForm, LostPasswordActivationForm



@login_required
def index(request):
    """
    A small view that displays a list of all users.
    See the template for the truely cool stuff.
    """
    users = User.objects.all().order_by('first_name', 'last_name')

    return render_to_response(request, 'usermanagement/index.html',
                                {'users' : users}) 


def loginview(request):
    """
    This view logs the user in.
    It has basicly 2 usage scenarios :
        1. A user uses the Loginform display on every page.
        So this view is requested via POST, username and password are checked
        and the user will be redirected to page whre he used the form.
        
        2. A logged out user tries to access a view protected by @login_required
        In this case @login_required will redirect him to this view via GET with
        next as a parameter.
        In this case a message asking the user ot log in will be displayed.
        The loginform context preprocessor will take the next from the GET request 
        and include it in the login form.
        Check usermanagment/context_processors.py for more information about,
        this mechanism.
        The rest is handled as described in 1. 
        
        For more information about loggin users in see :
        
    """
    if request.method == 'GET':
        return render_to_response(request, 'usermanagement/login.html')

    
    login_form = LoginForm(request.POST)
   
    if not login_form.is_valid():
        return render_to_response(request, 'usermanagement/error.html', {
            'error_message' : 'Bitte Username und Password eingeben.'})
    

    next = login_form.cleaned_data['next']   
    username = login_form.cleaned_data['username']
    password = login_form.cleaned_data['password']
    
    user = authenticate(username=username,password=password)


    if not user == None:

        if user.is_active:
            try:
                profile = user.get_profile()
                if not profile.activation_hash == '': # in case a user has lost his password but found again before changing it (hash!='' && active)
                    profile.activation_hash = ''
                    profile.save()
            except UserProfile.DoesNotExist:
                pass
                
            login(request,user)
            return redirect(next)
        else:
            return render_to_response(request, 'usermanagement/error.html', {
            'error_message' : 'User noch nicht aktiv.', 'back_link' : next})
    else: 
        return render_to_response(request, 'usermanagement/error.html', {
        'error_message' : 'User unbekannt.', 'back_link' : next})
            
            
            

def registerview(request):
    if request.user.is_authenticated(): # already logged-in users should not be here => redirect to their profile
        return HttpResponseRedirect("/")
    if request.method == 'POST': # If the form has been submitted...
        form = RegisterForm(request.POST,request.FILES)
        if form.is_valid(): # All validation rules pass

            email = form.cleaned_data['email']
            password = form.cleaned_data['password']
            
            first_name = form.cleaned_data['first_name']
            last_name = form.cleaned_data['last_name']
            
            # sets username to mail
            username = email
            
            user = User.objects.create_user(username, email, password)
            
            user.first_name = first_name
            user.last_name = last_name
            
            user.is_active = False
            
            user.save()
            
            # set the profile
            activation_hash = UserProfile.generate_activation_hash()
            
            profile = UserProfile(
                                    user = user,
                                    activation_hash = activation_hash,
                                 )
            profile.save(user)
            
            # build an absolute activation link
            activation_link = request.build_absolute_uri(reverse('usermanagement.views.activationview', kwargs={ 'email': email, 'activation_hash': activation_hash }))

            __send_activation_email(user, activation_link)
                        
            return render_to_response(request, 'usermanagement/register_complete.html')
    else:
        form = RegisterForm()

    return render_to_response(request, 'usermanagement/register.html', {
        'form': form,
    })
    
    
def activationview(request, activation_hash = '', email = ''):
    """ Deals with the activation of a User """
    try:
        user = User.objects.get(email=email)
    except User.DoesNotExist: # if the user does not exist render an error
        return render_to_response(request, 'usermanagement/error.html', {
            'error_message' : 'User existiert nicht. Bitte Admin kontaktieren.'})

    try:
        profile = user.get_profile()
    except UserProfile.DoesNotExist: # if there is no profile existent (which should NEVER EVER happen) render an error
        return render_to_response(request, 'usermanagement/error.html', {
            'error_message' : 'Profil für ' + username + ' existiert nicht ' + '. Bitte Admin kontaktieren.'})
    
    if profile.activation_hash == '': # if the hash is '' then the user has already been activated: render complete page in order to tell the user that the activation was successful
        return render_to_response(request, 'usermanagement/error.html', {
            'error_message' : 'User ' + username + ' ist schon aktiv'})
    
    if profile.activation_hash == activation_hash: # if the hash is equal to the real one: activate user, set hash to '' and render complete
        user.is_active = True
        user.save()
        profile.activation_hash = ''
        profile.save()
        return render_to_response(request, 'usermanagement/activation_complete.html', {
            'username':user,
            'activation_hash':activation_hash
        })
    return render_to_response(request, 'usermanagement/error.html', {
        'error_message' : 'User existiert nicht ' + username + ' mit Hash ' + activation_hash + '. Bitte Admin kontaktieren.'})

@login_required
def changepasswordview(request):
    if request.method == 'POST': # If the form has been submitted...
        form = ChangePasswordForm(request.POST)
        form.user = request.user
        if form.is_valid(): # All validation rules pass

            user = request.user
            
            # set new password
            user.set_password(form.cleaned_data['password']) # known to be valid (made sure in the form)
            
            user.save()
            
            return redirect("/")
    else:
        form = ChangePasswordForm() # An unbound form
        form.user = request.user

    return render_to_response(request, 'usermanagement/change_password.html', {
        'form': form,
    })

def lostpasswordview(request):
    """ This view is there to display the LostPasswordForm and send the reactivation mail """
    if request.method == 'POST': # If the form has been submitted...
        form = LostPasswordForm(request.POST)
        if form.is_valid(): # All validation rules pass
            email = form.cleaned_data['email']
            
            user = User.objects.get(email = email)
            
            activation_hash = UserProfile.generate_activation_hash()
            
            profile = user.get_profile()
            
            profile.activation_hash = activation_hash
            
            profile.save()
            
            # build an absolute activation link
            activation_link = request.build_absolute_uri(reverse('usermanagement.views.lostpasswordactivation', kwargs={ 'email': email, 'activation_hash': activation_hash }))
            
            __send_lostpassword_email(user, activation_link)
            
            return redirect("/")
    else:
        form = LostPasswordForm() # An unbound form

    return render_to_response(request, 'usermanagement/lost_password_form.html', {
        'form': form,
    })
    
def lostpasswordactivation(request, email = '', activation_hash = ''):
    """ Deals with the reactivation of a User """
    if request.method == 'POST': 
        form = LostPasswordActivationForm(request.POST)
        if form.is_valid(): # All validation rules pass
            user = None
            
            try:
                user = User.objects.get(email = email)
            except User.DoesNotExist: # if the user does not exist render an error
                return render_to_response(request, 'usermanagement/error.html', {
                    'error_message' : 'User existiert nicht. Bitte Admin kontaktieren.'})
            try:
                profile = user.get_profile()
            except UserProfile.DoesNotExist: # if there is no profile existent (which should NEVER EVER happen) render an error
                return render_to_response(request, 'usermanagement/error.html', {
                    'error_message' : 'Profil für ' + email + ' existiert nicht ' + '. Bitte Admin kontaktieren.'})
            if profile.activation_hash == '': # if the hash is '' then the user has already been activated: render complete page in order to tell the user that the activation was successful
                return render_to_response(request, 'usermanagement/error.html', {
                    'error_message' : 'User ' + email + ' ist schon reaktiviert worden.'})
            
            if profile.activation_hash == activation_hash: # if the hash is equal to the real one: set new password
                if user.is_active: # if the user is active do it
                    user.set_password(form.cleaned_data['password']) # known to be valid (made sure in the form)
                    user.save()
                    profile.activation_hash = ''
                    profile.save()
                
                    return render_to_response(request, 'usermanagement/lost_password_activation_complete.html')
                else: #if not: the user has not been activated => do nothing
                    return render_to_response(request, 'usermanagement/error.html', {
                        'error_message' : 'Der User wurde noch nicht aktiviert!'})
            else: # happens if a wrong hash is entered
                return render_to_response(request, 'usermanagement/error.html', {'error_message' : 'Du bist so ein 1337 Haxor, mensch... Wenn nicht: Bitte an Admins wenden.'})
    else:
        form = LostPasswordActivationForm() # An unbound form

    return render_to_response(request, 'usermanagement/lost_password_activation_form.html', {
        'form': form,
        'email': email,
        'activation_hash': activation_hash
    })

def __send_activation_email(user, activation_link):
    welcome_mail = EmailMessage('Aktivierungs-Link für uni.lotterm.org', # Header
        'Hallo!\n\nDu hast dich auf uni.lotterm.org angemeldet. \
        Um deinen Account freizuschalten, rufe bitte diese Url auf:\n ' + activation_link + '\n.',
        'TomLottermann@googlemail.com', # From
        [user.email] # To
    )
    
    welcome_mail.send()
    
def __send_lostpassword_email(user, activation_link):
     
    lost_password_mail = EmailMessage('Passwort verloren auf uni.lotterm.org', # Header
        'Hallo!\n\n \
        Um ein neues Passwort zu setzen, rufe bitte diese Url auf:\n ' + activation_link + '\n.',
        'TomLottermann@googlemail.com', # From
        [user.email] # To
    )
    
    lost_password_mail.send()
